import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { get } from '@/axios/api';

export function usePollingTask() {
    const pollingSignal = ref({ cancelled: false });
    let pollTimer: number | null = null;

    function stopPolling() {
        pollingSignal.value.cancelled = true;
        if (pollTimer !== null) {
            clearTimeout(pollTimer);
            pollTimer = null;
        }
    }

    async function pollTaskStatus(
        url: string,
        onSuccess: (result: any) => void,
        onFailure?: (err: any) => void,
        onPending?: (result: any) => void,
        opts?: { initialDelay?: number; maxDelay?: number; timeout?: number }
    ) {
        const initialDelay = opts?.initialDelay ?? 1000;
        const maxDelay = opts?.maxDelay ?? 10000;
        const overallTimeout = opts?.timeout ?? 5 * 60 * 1000;

        let attempt = 0;
        const startTs = Date.now();
        pollingSignal.value.cancelled = false;

        async function _tick(): Promise<void> {
            if (pollingSignal.value.cancelled) return;

            if (Date.now() - startTs > overallTimeout) {
                onFailure?.(new Error('Polling timeout'));
                ElMessage.error('任务超时（等待超过5分钟）');
                return;
            }

            try {
                const res: any = await get(url);
                const status = res.status;
                if (['PENDING', 'STARTED', 'RETRY'].includes(status)) {
                    attempt++;
                    const delay = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
                    if (pollingSignal.value.cancelled) return;
                    pollTimer = window.setTimeout(_tick, delay);
                    onPending?.(res)
                } else if (status === 'SUCCESS') {
                    onSuccess?.(res.result);
                } else if (status === 'FAILURE') {
                    onFailure?.(res.error ?? res.result ?? 'task failed');
                } else {
                    attempt++;
                    const delay = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
                    if (pollingSignal.value.cancelled) return;
                    pollTimer = window.setTimeout(_tick, delay);
                }
            } catch (err: any) {
                attempt++;
                const delay = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
                console.warn('pollTaskStatus request failed, retrying in', delay, 'ms', err);
                if (pollingSignal.value.cancelled) return;
                pollTimer = window.setTimeout(_tick, delay);
            }
        }

        await _tick();
    }

    return {
        pollTaskStatus,
        stopPolling,
        pollingSignal
    };
}
